package com.springsource.a05CommonBeanFactoryPostProcessor;


import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.io.IOException;

// 解析@Component注解
public class MyConfigurationClassPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        try {
            // 模拟@ComonentScan注解
            AnnotationBeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
            // 1、获取Config类上的@ComponentScan注解中的路径
            ComponentScan annotation = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);
            String[] packages = annotation.basePackages();
            for (String aPackage : packages) {
                String path = "classpath*:" + aPackage.replace(".", "/") + "/**/*.class";
                // 2、用资源加载器加载路径及其所有子路径下的class文件
                Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);
                CachingMetadataReaderFactory cachingMetadataReaderFactory = new CachingMetadataReaderFactory();
                for (Resource resource : resources) {
                    // 3、读取class文件的元信息
                    MetadataReader metadataReader = cachingMetadataReaderFactory.getMetadataReader(resource);
                    String className = metadataReader.getClassMetadata().getClassName();
                    System.out.println(className);
                    // 是否有@Component注解
                    boolean b = metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName());
                    // 是否有@Component派生注解
                    if (!b) {
                        b = metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName());
                    }
                    // 4、如果有@Component注解，则注册beanDefinition
                    if (b) {
                        BeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(className).getBeanDefinition();
                        ((DefaultListableBeanFactory) beanFactory).registerBeanDefinition(beanNameGenerator.generateBeanName(beanDefinition, (BeanDefinitionRegistry) beanFactory), beanDefinition);
                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}
